package com.bigfans.catalogservice.service.product;

import com.bigfans.catalogservice.dao.ProductDAO;
import com.bigfans.catalogservice.dao.ProductSpecDAO;
import com.bigfans.catalogservice.model.*;
import com.bigfans.catalogservice.service.sku.SkuService;
import com.bigfans.catalogservice.service.sku.StockService;
import com.bigfans.catalogservice.service.spec.SpecOptionService;
import com.bigfans.catalogservice.service.spec.SpecValueService;
import com.bigfans.framework.dao.BaseServiceImpl;
import com.bigfans.framework.event.ApplicationEventBus;
import com.bigfans.framework.plugins.FileStoragePlugin;
import com.bigfans.framework.utils.CollectionUtils;
import com.bigfans.model.event.ProductCreatedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 商品服务类
 *
 * @author lichong
 */
@Service(ProductServiceImpl.BEAN_NAME)
public class ProductServiceImpl extends BaseServiceImpl<Product> implements ProductService {

    public static final String BEAN_NAME = "productService";

    @Autowired
    private SpecValueService specValueService;
    @Autowired
    private SpecOptionService specOptionService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private StockService stockService;
    @Autowired
    private ProductImageService productImageService;
    @Autowired
    private ProductSpecDAO productSpecDAO;
    @Autowired
    private ApplicationEventBus eventBus;
    @Autowired
    private FileStoragePlugin fileStoragePlugin;

    private ProductDAO productDAO;

    @Autowired
    public ProductServiceImpl(ProductDAO productDAO) {
        super(productDAO);
        this.productDAO = productDAO;
    }

    @Override
    @Transactional(readOnly = true)
    public List<Product> listByCategory(String categoryId, Long start, Long pagesize) throws Exception {
        return productDAO.listByCategory(categoryId, start, pagesize);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Product> listByCategory(String[] categoryIdList, Long start, Long pagesize) throws Exception {
        return productDAO.listByCategory(categoryIdList, start, pagesize);
    }

    @Transactional
    public void create(Product prod, List<ProductImage> imgList, List<ProductSpec> specList) throws Exception {
        // 商品名字+规格值作为最终商品名
        StringBuilder nameBuilder = new StringBuilder(32);
        nameBuilder.append(prod.getName());
        specList.forEach((item) -> {
            nameBuilder.append(" ");
            nameBuilder.append(item.getValue());
        });
        prod.setName(nameBuilder.toString());

        // 创建商品
        super.create(prod);

        List<String> optionIds = new ArrayList<>();
        List<String> valueIds = new ArrayList<>();
        // 创建属性
        if (CollectionUtils.isNotEmpty(specList)) {
            for (ProductSpec ps : specList) {
                ps.setPgId(prod.getPgId());
                ps.setProdId(prod.getId());
                String optionId = ps.getOptionId();
                String value = ps.getValue();
                SpecOption specOption = specOptionService.load(optionId);
                switch (specOption.getInputType()) {
                    // 如果规格值是手动输入的,那么先创建规格值,传递过来的值为输入的内容,需要创建一个新的specValue
                    case SpecOption.INPUTTYPE_MANUL:
                        SpecValue existingVal = specValueService.getByValue(optionId , value);
                        if (existingVal == null) {
                            SpecValue sv = new SpecValue();
                            sv.setCategoryId(prod.getCategoryId());
                            sv.setOptionId(optionId);
                            sv.setValue(value);
                            specValueService.create(sv);
                            ps.setValueId(sv.getId());
                        } else {
                            ps.setValueId(existingVal.getId());
                        }
                        break;
                    // 如果是选择已存在的规格值,那么设置valueId,传递过来的值为选择的ID
                    case SpecOption.INPUTTYPE_LIST:
                        ps.setValueId(value);
                        break;
                    default:
                        break;
                }

                optionIds.add(ps.getOptionId());
                valueIds.add(ps.getValueId());
            }
            productSpecDAO.batchInsert(specList);
        }

        //创建SKU
        SKU sku = new SKU();
        sku.setPgId(prod.getPgId());
        sku.setProdId(prod.getId());
        sku.setOptKey(CollectionUtils.join(optionIds, SKU.KEYS_SEPARATOR));
        sku.setValKey(CollectionUtils.join(valueIds, SKU.KEYS_SEPARATOR));
        skuService.create(sku);

        // 创建库存
        Stock stock = new Stock();
        stock.setRest(prod.getStock());
        stock.setProdId(prod.getId());
        stock.setPgId(prod.getPgId());
        stockService.create(stock);

        // 创建图片
        if (imgList != null) {
            for (int i = 0; i < imgList.size(); i++) {
                ProductImage pi = imgList.get(i);
                pi.setProdId(prod.getId());
                pi.setPgId(prod.getPgId());
                pi.setOrderNum(i + 1);
                String path = pi.getPath();
                File srcFile = null;
                try {
                    // 获取页面传递过来的图片地址
                    srcFile = fileStoragePlugin.download(path);
                    // 生成缩略图,大图,小图等,并上传
                    productImageService.upload(pi, srcFile);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (srcFile != null) {
                        srcFile.deleteOnExit();
                    }
                    fileStoragePlugin.deleteFile(path);
                }
            }
        }

        // 更新缩略图
        ProductImage thumb = productImageService.getThumb(prod.getId());
        productDAO.updateThumb(prod.getId(), thumb.getPath());

        eventBus.publishEvent(new ProductCreatedEvent(prod.getId()));
    }

    @Transactional(readOnly = true)
    public Product getDetailById(String pid) throws Exception {
        Product product = super.load(pid);
        // 规格信息
        List<ProductSpec> specs = productSpecDAO.listByProdId(pid);
        product.setSpecList(specs);
        return product;
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProductSpec> listSpecsById(String pid) throws Exception {
        return productSpecDAO.listByProdId(pid);
    }

    /**
     * 商品下架
     *
     * @param productId
     * @throws Exception
     */
    @Transactional
    public void unMarketable(String productId) throws Exception {
        Product productEntity = new Product();
        productEntity.setId(productId);
        productEntity.setIsOnSale(false);
        update(productEntity);
    }

    /**
     * 商品上架
     *
     * @param productId
     * @throws Exception
     */
    @Transactional
    public void marketable(String productId) throws Exception {
        Product productEntity = new Product();
        productEntity.setId(productId);
        productEntity.setIsOnSale(true);
        update(productEntity);
    }

    @Override
    @Transactional
    public void updateHits(String prodId) throws Exception {
        productDAO.updateHits(prodId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Product> listByPgId(String pgId) throws Exception {
        return productDAO.listByPgId(pgId);
    }

    @Transactional(readOnly = true)
    public List<Product> listHotSale(Long start, Long pagesize) throws Exception {
        return productDAO.listHotSale(start, pagesize);
    }

}
